package topic

import (
	"context"
	"strconv"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/service/backend/common/errorx"
	"mall/service/backend/common/i18n"
	"mall/service/backend/common/utils/pointy"
	"mall/service/forum/model"
	"mall/service/forum/rpc/internal/svc"
	"mall/service/forum/rpc/internal/utils/errorhandler"
	"mall/service/forum/rpc/types/forum"

	"github.com/zeromicro/go-zero/core/logx"
)

type BackendGetTopicByIdLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBackendGetTopicByIdLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendGetTopicByIdLogic {
	return &BackendGetTopicByIdLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BackendGetTopicByIdLogic) BackendGetTopicById(in *forum.IDReq) (*forum.TopicInfo, error) {
	if in.Id == 0 {
		return nil, errorx.NewInvalidArgumentError(i18n.ValidationError)
	}

	res, err := l.svcCtx.Topic.FindOne(l.ctx, in.Id)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	var media []*forum.ForumMediaInfo
	mediaFilterMap := make(map[string]map[string][]any)
	mediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectID] = map[string][]any{
		"equalTo": []any{res.TopicID},
	}
	mediaFilterMap[model.ForumAttachmentRelationshipColumns.ObjectType] = map[string][]any{
		"equalTo": []any{globalkey.AttachmentLogTypeForumTopic},
	}
	var orderBy string = model.ForumAttachmentRelationshipColumns.AttachmentThumbnail + " DESC," +
		model.ForumAttachmentRelationshipColumns.AttachmentOrder
	mediaList, _, err := l.svcCtx.Topic.GetMedia(l.ctx, model.M{
		"orderBy": orderBy,
	}, -1, mediaFilterMap)
	if err != nil {
		return nil, err
	}

	if len(mediaList) > 0 {
		for _, v := range mediaList {
			media = append(media, &forum.ForumMediaInfo{
				Uid:       pointy.GetPointer(v.AttachmentRelationshipID),
				Id:        pointy.GetPointer(strconv.FormatInt(int64(v.AttachmentID), 10)),
				Uri:       pointy.GetPointer(v.AttachmentSource),
				Url:       pointy.GetPointer(v.AttachmentImageURL),
				Thumbnail: pointy.GetPointer(uint32(v.AttachmentThumbnail)),
				Order:     pointy.GetPointer(uint32(v.AttachmentOrder)),
				AltText:   pointy.GetPointer(v.AttachmentImageAlt),
				Meta:      pointy.GetPointer(v.AttachmentImageMeta),
			})
		}
	}

	var meta []*forum.ForumMetaInfo
	metaFilterMap := make(map[string]map[string][]any)
	metaFilterMap[model.ForumTopicMetumColumns.TopicID] = map[string][]any{
		"equalTo": []any{res.TopicID},
	}
	metaList, _, err := l.svcCtx.Topic.GetMeta(l.ctx, model.M{}, -1, metaFilterMap)
	if err != nil {
		return nil, err
	}

	if len(metaList) > 0 {
		for _, v := range metaList {
			key := v.MetaKey
			if len(key) > 0 && v.MetaValue.Valid {
				meta = append(meta, &forum.ForumMetaInfo{
					Id:    pointy.GetPointer(v.MetaID),
					Key:   pointy.GetPointer(key),
					Value: pointy.GetPointer(v.MetaValue.String),
				})
			}
		}
	}

	return &forum.TopicInfo{
		Id:           pointy.GetPointer(res.TopicID),
		ForumId:      pointy.GetPointer(res.ForumID),
		AuthorId:     pointy.GetPointer(res.TopicAuthorID),
		Title:        pointy.GetPointer(res.Title),
		Slug:         pointy.GetPointer(res.Slug),
		Status:       pointy.GetPointer(uint32(res.TopicStatus)),
		Sticky:       pointy.GetPointer(uint32(res.Sticky)),
		PostCount:    pointy.GetPointer(uint32(res.PostCount)),
		CommentCount: pointy.GetPointer(uint32(res.CommentCount)),
		CreatedAt:    pointy.GetPointer(modelx.FormatTime(res.TopicDate, "")),
		UpdatedAt:    pointy.GetPointer(modelx.FormatTime(res.TopicModifiedDate, "")),
		Author: &forum.ForumAuthorInfo{
			Id:        pointy.GetPointer(res.TopicAuthorID),
			Name:      pointy.GetPointer(res.TopicAuthorNickname),
			Email:     pointy.GetPointer(res.TopicAuthorEmail),
			Avatar:    pointy.GetPointer(res.TopicAuthorAvatar),
			Ip:        pointy.GetPointer(res.TopicAuthorIP),
			Level:     pointy.GetPointer(uint32(res.TopicAuthorRankID)),
			Anonymous: pointy.GetPointer(uint32(res.TopicAuthorAnonymous)),
		},
		Media: media,
		Meta:  meta,
	}, nil
}
